package com.rolerealm.service.impl;

import com.rolerealm.service.StreamingLLMService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.function.Consumer;

/**
 * 流式LLM服务实现
 * 
 * @author RoleRealm Team
 * @version 1.0.0
 */
@Slf4j
@Service
public class StreamingLLMServiceImpl implements StreamingLLMService {

    @Value("${llm.openai.apiKey:}")
    private String apiKey;

    @Value("${llm.openai.baseUrl:}")
    private String baseUrl;

    @Value("${llm.openai.timeoutSeconds:30}")
    private int timeoutSeconds;

    private final HttpClient httpClient = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(10))
            .build();

    @Override
    public void streamInfer(String prompt, String languageOrModel, 
                          Consumer<String> onChunk, 
                          Runnable onComplete, 
                          Consumer<Exception> onError) {
        
        if (apiKey == null || apiKey.isBlank()) {
            log.warn("OpenAI API Key 未配置，回退到简单回声");
            onChunk.accept("AI回复：" + (prompt == null ? "" : prompt));
            onComplete.run();
            return;
        }

        // 尝试多个模型，按优先级排序（通义千问优先）
        String[] models = {"qwen-max", "qwen-plus", "qwen-turbo", "deepseek-chat", "gpt-3.5-turbo"};
        String model = (languageOrModel == null || languageOrModel.isBlank()) ? models[0] : languageOrModel;
        String url = baseUrl.endsWith("/") ? (baseUrl + "v1/chat/completions") : (baseUrl + "/v1/chat/completions");

        String body = "{\n" +
                "  \"model\": \"" + escape(model) + "\",\n" +
                "  \"messages\": [\n" +
                "    {\"role\": \"system\", \"content\": \"You are RoleRealm AI.\"},\n" +
                "    {\"role\": \"user\", \"content\": " + toJsonString(prompt) + "}\n" +
                "  ],\n" +
                "  \"temperature\": 0.7,\n" +
                "  \"stream\": true\n" +
                "}";

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .timeout(Duration.ofSeconds(Math.max(5, timeoutSeconds)))
                .header("Authorization", "Bearer " + apiKey)
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8))
                .build();

        try {
            HttpResponse<String> response = httpClient.send(request, 
                HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
            
            if (response.statusCode() / 100 != 2) {
                log.error("流式API调用失败，status={} body={}", response.statusCode(), response.body());
                onError.accept(new RuntimeException("API调用失败: " + response.statusCode()));
                return;
            }

            // 处理流式响应
            processStreamResponse(response.body(), onChunk, onComplete, onError);
            
        } catch (Exception e) {
            log.error("调用流式API失败", e);
            onError.accept(e);
        }
    }

    private void processStreamResponse(String responseBody, 
                                     Consumer<String> onChunk, 
                                     Runnable onComplete, 
                                     Consumer<Exception> onError) {
        try {
            // 如果响应不是流式格式，直接返回完整内容
            if (!responseBody.contains("data:")) {
                String content = extractContentFromChatCompletions(responseBody);
                if (content != null && !content.isEmpty()) {
                    onChunk.accept(content);
                }
                onComplete.run();
                return;
            }
            
            String[] lines = responseBody.split("\n");
            StringBuilder content = new StringBuilder();
            
            for (String line : lines) {
                line = line.trim();
                if (line.startsWith("data: ")) {
                    String data = line.substring(6);
                    if ("[DONE]".equals(data)) {
                        onComplete.run();
                        return;
                    }
                    
                    // 解析JSON数据
                    String chunk = extractContentFromStreamData(data);
                    if (chunk != null && !chunk.isEmpty()) {
                        content.append(chunk);
                        onChunk.accept(chunk);
                    }
                }
            }
            
            // 如果没有找到[DONE]，直接完成
            onComplete.run();
            
        } catch (Exception e) {
            log.error("处理流式响应失败", e);
            onError.accept(e);
        }
    }

    private String extractContentFromStreamData(String data) {
        try {
            // 简单的JSON解析，提取content字段
            int contentStart = data.indexOf("\"content\":\"");
            if (contentStart == -1) {
                return null;
            }
            contentStart += 11; // 跳过 "content":"
            
            int contentEnd = data.indexOf("\"", contentStart);
            if (contentEnd == -1) {
                return null;
            }
            
            String content = data.substring(contentStart, contentEnd);
            // 处理转义字符
            return content.replace("\\n", "\n")
                         .replace("\\\"", "\"")
                         .replace("\\\\", "\\");
        } catch (Exception e) {
            log.warn("解析流式数据失败: {}", data, e);
            return null;
        }
    }

    private static String toJsonString(String text) {
        if (text == null) return "\"\"";
        String esc = text.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n");
        return "\"" + esc + "\"";
    }

    private String extractContentFromChatCompletions(String resp) {
        try {
            // 简单的JSON解析，提取choices[0].message.content
            int choicesStart = resp.indexOf("\"choices\":[");
            if (choicesStart == -1) return null;
            
            int messageStart = resp.indexOf("\"message\":", choicesStart);
            if (messageStart == -1) return null;
            
            int contentStart = resp.indexOf("\"content\":\"", messageStart);
            if (contentStart == -1) return null;
            contentStart += 11; // 跳过 "content":"
            
            int contentEnd = resp.indexOf("\"", contentStart);
            if (contentEnd == -1) return null;
            
            String content = resp.substring(contentStart, contentEnd);
            // 处理转义字符
            return content.replace("\\n", "\n")
                         .replace("\\\"", "\"")
                         .replace("\\\\", "\\");
        } catch (Exception e) {
            log.warn("解析聊天完成响应失败: {}", resp, e);
            return null;
        }
    }

    private String escape(String text) {
        if (text == null) return "";
        return text.replace("\\", "\\\\").replace("\"", "\\\"");
    }
}
